
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#include <stdio.h>
#include <stdlib.h>

void config_pins(void);
void config_longueur_rpm_pulse(void);
void config_dephasage_ign_pulse(void);
void config_longueur_impulsion_ign(void);
void rpm_pulse_start(void);   // demarre pulse RPM
void rpm_pulse_stop(void);    // arret pulse RPM
void ign_pulse_start(void);   // demarre pulse Allumage
void ign_pulse_stop(void);    // arret pulse Allumage
void RIT_IRQHandler(void);    // Simule Vitesse de Rotation Moteur = frequence des pulses RPM
void TIMER0_IRQHandler(void); // Longueur du Pulse RPM
void TIMER1_IRQHandler(void); // Dephasage Pulse IGN
void TIMER2_IRQHandler(void); // Longueur Impulsion IGN

volatile int flipflop = 0;
int main(void)
{
	volatile static int i = 0 ;
	char buf[64];
	float compteur = 0.0, pulse = 0.0;

	config_pins();
    config_longueur_rpm_pulse();
    config_dephasage_ign_pulse();
    config_longueur_impulsion_ign();

	// RIT prend comme source PCLKSEL1, bit 27 & 26
	// -> 00 =>  PCLK=CCLK/4, 01 => PCLK=CCLK, 10 => PCLK=CCLK/2, 11 => PCLK=CCLK/8
	// Soit PCLK pour RIT = CCLK/8 -> 100,000,000 [MHz]/8 = 12,500,000 [MHz] => 80 [ns]
	LPC_SC->PCLKSEL1 |= (1<<27)|(1<<26);
	LPC_SC->PCONP |= 1<<16;  // ! RIT est off au reset -> l'allumer avant utilisation

    do
	{
	 printf("RTI Demo - SysClock = %d [MHz] - RIT sur CCLK/4 -> resolution %d [ns]\n", SystemCoreClock, 1000000000/(SystemCoreClock/8));
	 printf("Pulse en [ms] ?");
	 scanf("%s", buf);
	 pulse = atof(buf);
	 pulse = pulse * 1000000.0; // en [ns]
	 compteur = pulse / 80.0;
	   if ( compteur > 4294967295.0 )
	   	printf("\n! DEPASSEMENT DU COMPTEUR (> 4.294.697.295)\n");
	} while ( compteur > 4294967295.0);

	printf("-> pour interruption RIT toutes les %f [ms], compteur RIT = %f \n", pulse, compteur);
	printf("Valeur 32 bit = %d\n",(uint32_t)compteur);

    NVIC_EnableIRQ(RIT_IRQn);

    LPC_RIT->RICOMPVAL = (uint32_t)compteur;
    // Quelques valeurs avec CCLK/4
    //LPC_RIT->RICOMPVAL = 0xffffffff; // 4.294.697.295 * 80E-09 = 343.56 sec = pulse MAX avec CCLK/8
    //LPC_RIT->RICOMPVAL = 62500000;   // 5 sec
    //LPC_RIT->RICOMPVAL = 62500000/5; // 1 sec
    //LPC_RIT->RICOMPVAL = 62500000*5; // 25 sec
    LPC_RIT->RIMASK = 0x00;

    // Pas d'effet Debug -> bit 2 a zero, Debug n'arretera pas le compteur
    LPC_RIT->RICTRL &= ~(1<<2);

    LPC_RIT->RICTRL |= (1<<1);  // clear Timer quand = a RICOMPVAL, on recommence a compter

    // Demarre RIT par bit 3
    LPC_RIT->RICTRL |= 1<<3;

	while(1)
	{
		for(i=0; i < 1500000; i++);
		//printf("RIT COUNTER = %d - %x (COMPARE=%x)\n", LPC_RIT->RICOUNTER, LPC_RIT->RICOUNTER, LPC_RIT->RICOMPVAL);
	}

	return 0 ;
}
void config_pins(void)
{
   LPC_GPIO1->FIODIR |= ( (1<<20)|(1<<19)|(1<<18) ); // P1.20, P1.19, P1.18 en sortie pull_up
   LPC_GPIO1->FIOMASK = 0;
   LPC_GPIO1->FIOCLR |= ( (1<<20)|(1<<19)|(1<<18) ); // P1.20, P1.19, P1.18 Off
}

// TIMER0 = longueur RPM
void config_longueur_rpm_pulse(void)
{
	LPC_SC->PCONP |= (1<<1);     // Timer0 On
	LPC_SC->PCLKSEL0 |= (1<<2);
	LPC_SC->PCLKSEL0 &= ~(1<<3); // Clock Timer3 = CCLK
	LPC_TIM0->PR = 0;			 // Prescaler
	LPC_TIM0->MR0 = 99999999/100;    // Si CCLK = 100 MHz -> Int. toutes les secondes
	LPC_TIM0->MCR = 3;	         // Interrupt and Reset on MR0
	NVIC_EnableIRQ(TIMER0_IRQn); // Enable timer interrupt
	LPC_TIM0->TCR = 2;     // Reset Timer0
	LPC_TIM0->TCR = 0;     // Stop timer, sera demarre par rpm_pulse_start
}

// TIMER1 = Dephasage IGN
void config_dephasage_ign_pulse(void)
{
	LPC_SC->PCONP |= (1<<2);     // Timer1 On
	LPC_SC->PCLKSEL0 |= (1<<4);
	LPC_SC->PCLKSEL0 &= ~(1<<5); // Clock Timer1 = CCLK
	LPC_TIM1->PR = 0;			 // Prescaler
	LPC_TIM1->MR0 = (99999999/100)*4;   // Si CCLK = 100 MHz -> Int. toutes les secondes
	LPC_TIM1->MCR = 3;	         // Interrupt and Reset on MR0
	NVIC_EnableIRQ(TIMER1_IRQn); // Enable timer interrupt
	LPC_TIM1->TCR = 2;     // Reset Timer0
	LPC_TIM1->TCR = 0;     // Stop timer, sera demarre par rpm_pulse_start
}
// TIMER2 = Longueur Impulsion IGN
void config_longueur_impulsion_ign(void)
{
	LPC_SC->PCONP |= (1<<22);     // Timer2 On
	LPC_SC->PCLKSEL1 |= (1<<12);
	LPC_SC->PCLKSEL1 &= ~(1<<13); // Clock Timer2 = CCLK
	LPC_TIM2->PR = 0;			 // Prescaler
	LPC_TIM2->MR0 = 99999999/50;    // Si CCLK = 100 MHz -> Int. toutes les secondes
	LPC_TIM2->MCR = 3;	         // Interrupt and Reset on MR0
	NVIC_EnableIRQ(TIMER2_IRQn); // Enable timer interrupt
	LPC_TIM2->TCR = 2;     // Reset Timer0
	LPC_TIM2->TCR = 0;     // Stop timer, sera demarre par ign_pulse_start
}

// TIMER0 = Longueur Impulsion RPM
void rpm_pulse_start(void)
{
  LPC_GPIO1->FIOSET |= (1<<20);
  // Demarre Temporisateur Longueur de Pulse RPM
	LPC_TIM0->TCR = 2;     // Reset Timer0
	LPC_TIM0->TCR = 1;     // Start timer
  // Demarre Dephasage IGN/RPM
    LPC_TIM1->TCR = 2;
    LPC_TIM1->TCR = 1;
}
void rpm_pulse_stop(void)
{
  LPC_GPIO1->FIOCLR |= (1<<20);
  LPC_TIM0->TCR = 0;  // Stop le timer de longueur d'impulsion RPM
}

void ign_pulse_start(void)
{
  LPC_GPIO1->FIOSET |= (1<<19);
  // Demarre Temporisateur Longueur de Pulse IGN
	LPC_TIM2->TCR = 2;     // Reset Timer0
	LPC_TIM2->TCR = 1;     // Start timer
}
void ign_pulse_stop(void)
{
  LPC_GPIO1->FIOCLR |= (1<<19);
  LPC_TIM1->TCR = 0; // Stop le timer de dephasage
  LPC_TIM2->TCR = 0; // Stop le timer de longueur de d'impulsion IGN
}

// Longueur Pulse RPM
void TIMER0_IRQHandler(void)
{
	if ( (LPC_TIM0->IR & (1<<0)) == (1<<0) )
	{
	 //printf("TIMER0\n");
	 LPC_TIM0->IR |= (1<<0); // RAZ Int.
     rpm_pulse_stop(); // Arrete le pulse quand le timer0 arrive a la match value
	}
}

// Dephasage Pulse IGN
void TIMER1_IRQHandler(void)
{
	if ( (LPC_TIM1->IR & (1<<0)) == (1<<0) )
	{
	 //printf("TIMER1\n");
	 LPC_TIM1->IR |= (1<<0); // RAZ Int.
     ign_pulse_start(); // on est arrive a la valeur de dephasage -> demarre le pulse
	}
}

// Longueur Pulse IGN
void TIMER2_IRQHandler(void)
{
	if ( (LPC_TIM2->IR & (1<<0)) == (1<<0) )
	{
	 //printf("TIMER2\n");
	 LPC_TIM2->IR |= (1<<0); // RAZ Int.
     ign_pulse_stop(); // Arrete le pulse quand le timer0 arrive a la match value
	}
}

// Simulation RPM
void RIT_IRQHandler(void)
{
	LPC_RIT->RICTRL |= 1<<0;   // RAZ Int (bien utiliser |= sinon manipulation des autres bit !)
//	printf("RIT IRQ! -> RIT COUNTER = %d (COMPARE=%x)\n", LPC_RIT->RICOUNTER, LPC_RIT->RICOMPVAL);
	// Demarre Pulse RPM
	rpm_pulse_start();
}

